package log

import (
	"Hypnos-Soundcore/constants"
	"fmt"
	"strings"
	"time"
)

// const .
const (
	DateFormat   = "2006-01-02T15:04:05-0700"
	EmptyDefault = "-"
	EmptyLatency = 0
)

// BuildLogV1 .
func BuildLogV1(tag string, a ...interface{}) string {
	ex := constants.ExtraRequest{ExTag: tag}
	return BuildActionLog(&ex, a...)
}

// BuildLogV2 .
func BuildLogV2(tag string, format string, a ...interface{}) string {
	ex := constants.ExtraRequest{ExTag: tag}
	return BuildActionLog(&ex, fmt.Sprintf(format, a...))
}

// BuildLogV3 .
func BuildLogV3(tag string, actionID, actionSubID string, errMsg string, latency int64, a ...interface{}) string {
	ex := constants.ExtraRequest{ExTag: tag, ExActionID: actionID, ExActionSubID: actionSubID,
		ExErrMsg: errMsg, ExLatency: latency}
	return BuildActionLog(&ex, a...)
}

// BuildLogV4 .
func BuildLogV4(tag string, actionID string, format string, a ...interface{}) string {
	ex := constants.ExtraRequest{ExTag: tag, ExActionID: actionID}
	return BuildActionLog(&ex, fmt.Sprintf(format, a...))
}

// 若字串为空则返回"-"
func adjustValue(value string) string {
	if len(value) == 0 {
		return EmptyDefault
	}
	return value
}

// 替换换行符
func replaceNewline(src string) string {
	if len(src) > 0 {
		src = strings.Replace(src, "\r\n", "##", -1)
		src = strings.Replace(src, "\n", "##", -1)
	}
	return src
}

// BuildAccessLog .
// log access specification
// level [time] "service" -- "path" "app_version" "phone_model" token open_udid country language
// request_id user_id station_sn device_sn latency code "message" params
func BuildAccessLog(bs constants.IBaseRequest, ex *constants.ExtraRequest) string {
	return fmt.Sprintf("[%s] \"%s\" -- \"%s\" \"%s\" \"%s\" %s %s %s %s %s %s %s %s %d %d \"%s\" %s",
		time.Now().Format(DateFormat), constants.ServerName(), adjustValue(ex.ExPath), adjustValue(bs.GetAppVersion()),
		adjustValue(bs.GetPhoneModel()), adjustValue(bs.GetAuthToken()), adjustValue(bs.GetOpenUdid()),
		adjustValue(bs.GetCountry()), adjustValue(bs.GetLanguage()), adjustValue(bs.GetRequestID()),
		adjustValue(ex.ExUserID), adjustValue(ex.ExStationSn), adjustValue(ex.ExDeviceSn), ex.ExLatency,
		ex.ExCode, adjustValue(replaceNewline(ex.ExMessage)), adjustValue(ex.ExParams))
}

// BuildActionLog .
// log normal specification
// level [time] "service" ~~ "tag" action_id action_sub_id latency "error" message
func BuildActionLog(ex *constants.ExtraRequest, a ...interface{}) string {
	return fmt.Sprintf("[%s] \"%s\" ~~ \"%s\" %s %s %d \"%s\" %s",
		time.Now().Format(DateFormat), constants.ServerName(), adjustValue(ex.ExTag), adjustValue(ex.ExActionID),
		adjustValue(ex.ExActionSubID), ex.ExLatency, adjustValue(replaceNewline(ex.ExErrMsg)), replaceNewline(fmt.Sprint(a...)))
}

// DebugPrintln print debug info
func DebugPrintln(tag string, a ...interface{}) {
	Debugf(BuildLogV1(tag, a...))
}

// DebugPrintf print debug info
func DebugPrintf(tag string, format string, a ...interface{}) {
	Debugf(BuildLogV2(tag, format, a...))
}

// DebugActionPrintln print debug info
func DebugActionPrintln(tag string, actionID, actionSubID string, errMsg string, latency int64, a ...interface{}) {
	Debugf(BuildLogV3(tag, actionID, actionSubID, errMsg, latency, a...))
}

// DebugAccessPrintln print debug info
func DebugAccessPrintln(bs constants.IBaseRequest, ex *constants.ExtraRequest) {
	Debugf(BuildAccessLog(bs, ex))
}

// WarningPrintln print warning info
func WarningPrintln(tag string, a ...interface{}) {
	Warningf(BuildLogV1(tag, a...))
}

// WarningPrintf print warning info
func WarningPrintf(tag string, format string, a ...interface{}) {
	Warningf(BuildLogV2(tag, format, a...))
}

// WarningActionPrintln print debug info
func WarningActionPrintln(tag string, actionID, actionSubID string, errMsg string, latency int64, a ...interface{}) {
	Warningf(BuildLogV3(tag, actionID, actionSubID, errMsg, latency, a...))
}

// WarningAccessPrintln print debug info
func WarningAccessPrintln(bs constants.IBaseRequest, ex *constants.ExtraRequest) {
	Warningf(BuildAccessLog(bs, ex))
}

// ErrorPrintln print error info
func ErrorPrintln(tag string, a ...interface{}) {
	Errorf(BuildLogV1(tag, a...))
}

// ErrorPrintf print error info
func ErrorPrintf(tag string, format string, a ...interface{}) {
	Errorf(BuildLogV2(tag, format, a...))
}

// ErrorActionPrintln print debug info
func ErrorActionPrintln(tag string, actionID, actionSubID string, errMsg string, latency int64, a ...interface{}) {
	Errorf(BuildLogV3(tag, actionID, actionSubID, errMsg, latency, a...))
}

// ErrorAccessPrintln print debug info
func ErrorAccessPrintln(bs constants.IBaseRequest, ex *constants.ExtraRequest) {
	Errorf(BuildAccessLog(bs, ex))
}
